# -*- coding: utf-8 -*-

# -------------------------------
# Author    : linlingwei
# Email     : 951035650@qq.com
# File Name : fMouth.py
# Date      : 2019/9/10 
# IDE       : PyCharm
# Version   : 1.1.12
# -------------------------------
import copy
import traceback

import maya.cmds as mc
import maya.mel as mel

import configs.constants.facial_constant as fc
import configs.constants.global_constant as gc
import configs.constants.suffix_constant as sc
import configs.constants.nodeType_constant as ntc
import configs.constants.attribute_constant as ac

import scripts.commonCmds as con
reload(con)
import scripts.curveCmds as cr
import scripts.deformerCmds as dc
reload(dc)
import rig.facial.fCore as fCore
reload(fCore)

class Mouth(fCore.FacialCore):
    def __init__(self):
        super(Mouth,self).__init__(fc.mouth)
        self.transform_init()
    
    def create(self):
        try:
            self.jaw_loc()
            self.lip_driver_loc()
            # self.lip_curve_driver()
            self.control()
            self.secondControl()
            self.hide_doDelete()
        except:
            traceback.print_exc()
        return
    
    def jaw_loc(self):
        
        jaw_tmp = con.lname("tmp",fc.jaw)
        
        rot_jaw = mc.spaceLocator(name = con.lname(fc.jaw,"rot",sc.sLoc))[0]
        mc.delete(mc.parentConstraint(jaw_tmp,rot_jaw,mo=False))
        mc.parent(rot_jaw,self.local_static)
        con.emptyGroup(rot_jaw)
        pt_jaw_loc = mc.spaceLocator(name=con.lname(fc.jaw,"point", sc.sLoc))[0]
        mc.parent(pt_jaw_loc,rot_jaw,r=True)
        pt_jaw = mc.createNode(ntc.tJoint,name=con.lname(fc.jaw,"point",sc.sJot),parent=pt_jaw_loc)
        # mc.parent(pt_jaw,rot_jaw)
        con.emptyGroup(pt_jaw_loc)
        # mc.hide(rot_jaw)
        con.hideShape(rot_jaw,pt_jaw_loc)
        mc.setAttr(pt_jaw+".radius",0.2)
        
        mc.sets(pt_jaw,include=self.local_sets)
        return
    
    def lip_driver_loc(self):
        
        #todo : base loc
        slider_tmp_crv = con.lname(fc.mouth,"tmp",fc.lip,"slider",fc.main,sc.sCrv)
        slider_crv = con.copyCurve(slider_tmp_crv,name=con.lname(fc.mouth,fc.lip,"slider",fc.main,sc.sCrv))
        mc.parent(slider_crv,self.local_static)
        up_tmp_crv = con.lname(fc.mouth,"tmp",fc.up,fc.lip,sc.sCrv)
        lo_tmp_crv = con.lname(fc.mouth,"tmp",fc.lo,fc.lip,sc.sCrv)
        lf_tmp = con.lname(fc.lf,"tmp",fc.corner)
        rt_tmp = con.lname(fc.rt,"tmp",fc.corner)

        lf_ul_tmp = con.lname(fc.lf, "tmp", fc.corner,fc.ul+"Max")
        lf_lr_tmp = con.lname(fc.lf, "tmp", fc.corner,fc.lr+"Max")
        sv = mc.getAttr(lf_ul_tmp+".ty")*0.1

        lr_max_par = con.getObjInCrvParameter(slider_crv,lf_lr_tmp)
        lr_par = con.getObjInCrvParameter(slider_crv,lf_tmp)
        
        offset_par = abs(lr_max_par-lr_par)
        
        up_cvs = mc.ls(up_tmp_crv+".cv[*]",fl=True)
        lo_cvs = mc.ls(lo_tmp_crv+".cv[*]",fl=True)
        _pt = mc.xform(up_cvs[0],q=True,ws=True,t=True)
        lf_pt = abs(_pt[0]),_pt[1],_pt[2]
        rt_pt = -abs(_pt[0]), _pt[1], _pt[2]
    
        lf_loc = mc.spaceLocator(name = con.lname(fc.lf,fc.mouth,fc.lip,fc.main,sc.sLoc))[0]
        # mc.setAttr(lf_loc+".t",abs(_pt[0]),_pt[1],_pt[2])
        mc.delete(mc.parentConstraint(lf_tmp,lf_loc,mo=False))
        mc.delete(mc.scaleConstraint(lf_tmp,lf_loc,mo=False))

        rt_loc = mc.spaceLocator(name = con.lname(fc.rt,fc.mouth,fc.lip,fc.main,sc.sLoc))[0]
        # mc.setAttr(rt_loc+".t",-abs(_pt[0]),_pt[1],_pt[2])
        mc.delete(mc.parentConstraint(lf_tmp,rt_loc,mo=False))
        mc.delete(mc.scaleConstraint(lf_tmp,rt_loc,mo=False))
        con.localMirror(rt_loc,space="world")

        mid_num = (len(up_cvs)-1)/2
        _pt = mc.xform(up_cvs[mid_num],q=True,ws=True,t=True)
        up_pt = 0,_pt[1],_pt[2]
        up_loc = mc.spaceLocator(name = con.lname(fc.mouth,fc.lip,fc.up,fc.main,sc.sLoc))[0]
        mc.setAttr(up_loc+".t",_pt[0],_pt[1],_pt[2])
        
        _pt = mc.xform(lo_cvs[mid_num],q=True,ws=True,t=True)
        lo_pt = 0,_pt[1],_pt[2]
        lo_loc = mc.spaceLocator(name = con.lname(fc.mouth,fc.lip,fc.lo,fc.main,sc.sLoc))[0]
        mc.setAttr(lo_loc+".t",_pt[0],_pt[1],_pt[2])
        
        mc.parent(lf_loc,rt_loc,up_loc,self.local_static)
        mc.parent(lo_loc,con.lname(fc.jaw,"point",sc.sLoc))
        
        driver_key = self.lip_open_frameCache()
        slider_key = self.lip_slider_frameCache()
        mc.setAttr(up_loc+".s",sv,sv,sv)
        mc.setAttr(lo_loc+".s",sv,sv,sv)

        dri_loc = [lf_loc,rt_loc,up_loc,lo_loc]
        mc.hide(dri_loc)
        for dl in dri_loc:
            # mc.setAttr(dl+".s",sv,sv,sv)
            con.emptyGroup(dl)
        
        _attr = con.lname(fc.lf,fc.corner,ac.height)
        mc.addAttr(self.local_static,ln=_attr,at="float",dv=.5,min=0,max=1,k=True)
        ch_ree = mc.createNode(ntc.tReverse, name=con.lname(_attr,sc.sRee))
        mc.connectAttr(con.lAttr(self.local_static,_attr),ch_ree+".ix")
        _attr = con.lname(fc.rt,fc.corner,ac.height)
        mc.addAttr(self.local_static,ln=_attr,at="float",dv=0.5,min=0,max=1,k=True)
        ch_ree = mc.createNode(ntc.tReverse, name=con.lname(_attr,sc.sRee))
        mc.connectAttr(con.lAttr(self.local_static,_attr),ch_ree+".ix")

        for lr in [fc.lf, fc.rt]:
            _ul_attr = con.lname(lr,fc.mouth,fc.lip,fc.ul)
            mc.addAttr(self.local_static, ln=_ul_attr, at="float", dv=0, k=True)
            
            _pma = mc.createNode(ntc.tPlusMinusAverage,name = con.lname(_ul_attr,sc.sPma))
            x,y,z = mc.xform(lf_ul_tmp,q=True,ws=True,t=True)
            mc.setAttr(_pma+".i3[0]",x,y,z)
            x,y,z = mc.xform(lf_loc,q=True,ws=True,t=True)
            mc.setAttr(_pma+".i3[1]",x,y,z)
            mc.setAttr(_pma+".op",2)
            
            _md = mc.createNode(ntc.tMultiplyDivide,name = con.lname(_ul_attr,sc.sMd))
            mc.connectAttr(_pma+".o3",_md+".i1")
            mc.connectAttr(con.lAttr(self.local_static,_ul_attr),_md+".i2x")
            mc.connectAttr(con.lAttr(self.local_static,_ul_attr),_md+".i2y")
            mc.connectAttr(con.lAttr(self.local_static,_ul_attr),_md+".i2z")
            
            ul_grp = con.emptyGroup(con.lname(lr,fc.mouth,fc.lip,fc.main,sc.sLoc),[fc.ul])[0]
            mc.connectAttr(_md+".o",ul_grp+".t")
            
            # ---
            #
            # _soft_attr = con.lname(lr, fc.mouth, fc.lip, ac.soft)
            # mc.addAttr(self.local_static, ln=_soft_attr, at="float", dv=0, k=True)
            # dn=con.lAttr(con.lname(lr,fc.mouth,fc.lip,fc.main,sc.sLoc),"sy")
            # dr =con.lAttr(self.local_static, _soft_attr)
            # mc.setDrivenKeyframe(dn, cd=dr, dv=0, v=1, itt="linear",ott="linear")
            # mc.setDrivenKeyframe(dn, cd=dr, dv=10, v=0.01, itt="linear",ott="linear")
            _slider_attr = con.lname(lr, fc.mouth, fc.lip, "slider")
            mc.addAttr(self.local_static, ln=_slider_attr, at="float", dv=0, k=True)
            mc.addAttr(self.local_static, ln=con.lname(_slider_attr, ac.offset), at="float", dv=0, k=True)
            if lr == fc.lf:
                mc.setAttr(con.lAttr(self.local_static,con.lname(_slider_attr, ac.offset)),-offset_par,l=True)
            else:
                mc.setAttr(con.lAttr(self.local_static,con.lname(_slider_attr, ac.offset)),offset_par,l=True)


        #todo : open mouth driver
        skinBase_crv_list = list()
        skinWire_crv_list = list()
        for ul,pt in zip([fc.up,fc.lo],[up_pt,lo_pt]):
            
            # todo : mouth corner control
            _ul_main_loc = con.lname(fc.mouth,fc.lip,ul,fc.main,sc.sLoc)
            l_pc = mc.parentConstraint(_ul_main_loc,lf_loc+"_Con",mo=True)[0]
            mc.setAttr(l_pc+".interpType",2)
            r_pc = mc.parentConstraint(_ul_main_loc,rt_loc+"_Con",mo=True)[0]
            mc.setAttr(r_pc+".interpType",2)

            for lp,_lr in zip([l_pc,r_pc],[fc.lf,fc.rt]):
                wal = mc.parentConstraint(lp,q=True,wal=True)
                if ul == fc.up:
                    mc.connectAttr(con.lAttr(self.local_static,con.lname(_lr,fc.corner,ac.height)),
                                   con.lAttr(lp,wal[-1]))
                else:
                    mc.connectAttr(con.lAttr(con.lname(_lr,fc.corner,ac.height,sc.sRee),"ox"),
                                   con.lAttr(lp,wal[-1]))
            
            _lf_loc = mc.spaceLocator(name=con.lname(fc.lf,fc.mouth,fc.lip,ul,sc.sLoc))[0]
            mc.delete(mc.pointConstraint(lf_loc,_lf_loc,mo=False))
            mc.setAttr(_lf_loc+".ty",pt[1])
            mc.parent(_lf_loc,lf_loc)
            _rt_loc = mc.spaceLocator(name=con.lname(fc.rt,fc.mouth,fc.lip,ul,sc.sLoc))[0]
            mc.delete(mc.pointConstraint(rt_loc,_rt_loc,mo=False))
            mc.setAttr(_rt_loc+".ty",pt[1])
            mc.parent(_rt_loc,rt_loc)
            
            _cr_loc = mc.spaceLocator(name=con.lname(fc.mouth, fc.lip, ul, sc.sLoc))[0]
            # mc.delete(mc.pointConstraint(con.lname(fc.mouth,fc.lip,ul,fc.main,sc.sLoc), _cr_loc, mo=False))
            
            mc.parent(_cr_loc, _ul_main_loc)

            con.channelAttrToDefault(_cr_loc)
            mc.parent(_cr_loc,self.local_static)
            _cr_loc_grp = con.emptyGroup(_cr_loc)
            mc.parentConstraint(_ul_main_loc,_cr_loc_grp[1],mo=True)
            
            # todo : base control
            _grp = mc.createNode(ntc.tTransform,name=con.lname(fc.mouth, fc.lip, ul, sc.sCrv,sc.sGrp),
                                 parent=self.local_static)
            
            loc_list = self.lip_driver_ctrPoint(ul,sc.sCtr)
            _pts = [mc.xform(l, q=True, ws=True, t=True) for l in loc_list]
            main_crv = mc.rename(mc.curve(p=_pts, d=3), con.lname(fc.mouth, fc.lip, ul, fc.main, sc.sCrv))
            mc.hide(main_crv)
            mc.parent(main_crv,_grp)
            self.parentConstraint_driver(loc_list, driver_key, _lf_loc, _rt_loc, _cr_loc)
            for loc,cv in zip(loc_list,range(len(loc_list))):
                locShape = con.findRelatedShape(loc)
                mc.connectAttr(locShape+".wp",main_crv+".cp[%s]"%cv)
            # todo : skin joint curve
            
            skin_loc_list = self.lip_driver_ctrPoint(ul, "skin")
            
            _pts = [mc.xform(l, q=True, ws=True, t=True) for l in skin_loc_list]
            skinBase_main_crv = mc.rename(mc.curve(p=_pts, d=3), con.lname(fc.mouth, fc.lip, ul, "skinBase", sc.sCrv))
            mc.hide(skinBase_main_crv)
            mel.eval(
                'rebuildCurve -ch 0 -rpo 1 -rt 0 -end 1 -kr 0 -kcp 0 -kep 1 -kt 0 -s 0 -d 3 -tol 0.01 "%s";' % skinBase_main_crv)

            skinWire_crv = con.copyCurve(skinBase_main_crv,con.lname(fc.mouth, fc.lip, ul, "skinWire", sc.sCrv))
            sk_wire = mc.wire(skinWire_crv,w=main_crv,dds=[0,100000],name=con.lname(skinWire_crv,sc.sWire))[0]
            mc.setAttr(sk_wire + ".rotation", 0)
            skinBase_main_crvShape = con.findRelatedShape(skinBase_main_crv)
            for i,loc in enumerate(skin_loc_list):
                poci = mc.createNode(ntc.tPointOnCurveInfo,name = con.lname(fc.mouth, fc.lip, ul, "skinBase", i,sc.sPoci))
                mc.connectAttr(skinBase_main_crvShape+".ws",poci+".ic")
                mc.setAttr(poci+".top",1)
                par = con.getObjInCrvParameter(skinBase_main_crv,loc)
                # print par
                mc.setAttr(poci+".pr",par)
                # loc_trans = con.emptyGroup(loc,["point"])[0]
                mc.connectAttr(poci+".p",loc+"_Zero.t")

            self.parentConstraint_driver(skin_loc_list, driver_key, _lf_loc, _rt_loc, _cr_loc,skip=True)
            skinBase_crv_list.append(skinBase_main_crv)
            skinWire_crv_list.append(skinWire_crv)
            mc.parent(skinBase_main_crv,skinWire_crv, _grp)
            
            
            for lr in [fc.lf,fc.rt]:
                # _slider_attr = con.lname(lr,fc.mouth,fc.lip,"slider")
                # mc.addAttr(self.local_static, ln=_slider_attr, at="float", dv=0, k=True)
                # mc.addAttr(self.local_static, ln=con.lname(_slider_attr, ac.offset), at="float", dv=0, k=True)
                #
                self.lip_slider(lr,loc_list,slider_crv,slider_key)
                # todo skin joint slider setting
                # self.lip_slider(lr, skin_loc_list, slider_crv, slider_key)
        # sb_up_crv,sb_lo_crv = skinBase_crv_list
        
        # todo : lip zip setting
        for _crv,_tag,i in zip(skinWire_crv_list,[fc.up,fc.lo],[1,0]):
            _grp = con.lname(fc.mouth, fc.lip, _tag, sc.sCrv,sc.sGrp)
            sb_crv_list = list()
            for _t in ["To","Dr","Zip","Output"]:
                sb_crv = con.copyCurve(_crv,name=con.lname(fc.mouth, fc.lip, _tag, _t, sc.sCrv))
                sb_crv_list.append(sb_crv)
            mc.hide(_crv,sb_crv_list)
            mc.parent(sb_crv_list, _grp)
            _wire = mc.wire(sb_crv_list[0],w=skinWire_crv_list[i],dds=[0,100000],name=con.lname(sb_crv_list[0],sc.sWire) )
            zip_wire = mc.wire(sb_crv_list[2], w=_crv,dds=[0,100000],name=con.lname(sb_crv_list[2],sc.sWire))

            _bls = mc.blendShape(_crv,sb_crv_list[0],sb_crv_list[1],w=[(0,.5),(1,.5)],
                                 name=con.lname(sb_crv_list[1],sc.sBls))[0]
            zip_bls = mc.blendShape(sb_crv_list[1],sb_crv_list[2],w=[0,0],
                                    name=con.lname(sb_crv_list[2],sc.sBls))[0]
            output_bls = mc.blendShape(sb_crv_list[1],sb_crv_list[2],sb_crv_list[3],w=[(0,0),(1,1)],
                                       name=con.lname(sb_crv_list[3],sc.sBls))[0]
            

            _attr = con.lname(fc.mouth, fc.lip,_tag, "zip",ac.height)
            mc.addAttr(_grp, ln=_attr, at="float", dv=5, min=0, max=10, k=True)
            _v= [0,1]
            if _tag == fc.lo:
                _v.reverse()
            mc.setDrivenKeyframe(con.lAttr(_bls,_crv),cd=con.lAttr(_grp,_attr),dv=0,v=_v[0],itt="linear",ott="linear")
            mc.setDrivenKeyframe(con.lAttr(_bls,_crv),cd=con.lAttr(_grp,_attr),dv=10,v=_v[1],itt="linear",ott="linear")
            
            mc.setDrivenKeyframe(con.lAttr(_bls,sb_crv_list[0]),cd=con.lAttr(_grp,_attr),dv=0,v=_v[1],itt="linear",ott="linear")
            mc.setDrivenKeyframe(con.lAttr(_bls,sb_crv_list[0]),cd=con.lAttr(_grp,_attr),dv=10,v=_v[0],itt="linear",ott="linear")
            con.transferAttr(_grp,self.local_static,(_attr,))

            _attr = con.lname(fc.mouth, fc.lip,_tag, fc.cl)
            mc.addAttr(_grp, ln=_attr, at="float", dv=0, min=0, max=10, k=True)

            mc.setDrivenKeyframe(con.lAttr(output_bls, sb_crv_list[1]), cd=con.lAttr(_grp, _attr), dv=0, v=0, itt="linear",
                                 ott="linear")
            mc.setDrivenKeyframe(con.lAttr(output_bls, sb_crv_list[1]), cd=con.lAttr(_grp, _attr), dv=10, v=1, itt="linear",
                                 ott="linear")

            mc.setDrivenKeyframe(con.lAttr(output_bls, sb_crv_list[2]), cd=con.lAttr(_grp, _attr), dv=0, v=1, itt="linear",
                                 ott="linear")
            mc.setDrivenKeyframe(con.lAttr(output_bls, sb_crv_list[2]), cd=con.lAttr(_grp, _attr), dv=10, v=0, itt="linear",
                                 ott="linear")
            con.transferAttr(_grp,self.local_static,(_attr,))

            mc.blendShape(sb_crv_list[3],skinBase_crv_list[1-i],w=[0,1],name=con.lname(skinBase_crv_list[1-i],sc.sBls))
            
            for _w in [_wire,zip_wire]:
                mc.setAttr(_w[0]+".rotation",0)

        return
    def lip_zip(self):
  
        return
    
    def lip_slider(self,prefix,loc_list,slider_crv,driver_key):
        
        lname = con.lname(prefix,fc.mouth,fc.lip,"slider")
        slider_crvShape = con.findRelatedShape(slider_crv)
        mc.hide(slider_crv)
        # if prefix == fc.rt:
        #     loc_list = copy.deepcopy(loc_list)
        #     loc_list.reverse()
        for i,loc in enumerate(loc_list):
            loc_count = mc.getAttr(loc + ".parameter")
            par = con.getObjInCrvParameter(slider_crv,loc)
            poci = mc.createNode(ntc.tPointOnCurveInfo,name = con.lname(lname,i,sc.sPoci))
            mc.connectAttr(slider_crvShape+".ws",poci+".ic")
            mc.setAttr(poci+".top",1)
            mc.setAttr(poci+".pr",par)
            
            px,py,pz = mc.getAttr(poci+".p")[0]
            v_pma = mc.createNode(ntc.tPlusMinusAverage,name = con.lname(lname,i,sc.sPma))
            mc.connectAttr(poci+".p",v_pma+".i3[0]",)
            # mc.connectAttr(loc+"_Zero.t",v_pma+".i3[1]",)
            mc.setAttr(v_pma+".i3[1]",px,py,pz)
            mc.setAttr(v_pma+".op",2)
            
            trans = con.emptyGroup(loc,[prefix+"Slider"])[0]
            mc.connectAttr(v_pma+".o3",trans+".t")
            _attr = con.lname(prefix,ac.offset)
            mc.addAttr(loc,ln=_attr,at="float",dv=0,k=True)
            adl = mc.createNode(ntc.tAddDoubleLinear,name=con.lname(lname,i,sc.sAdl))
            mc.setAttr(adl+".i1",par)
            mc.connectAttr(con.lAttr(loc,_attr),adl+".i2")
            mc.connectAttr(adl+".o",poci+".pr")
            
            mdl = mc.createNode(ntc.tMultDoubleLinear,name=con.lname(lname,i,sc.sMdl))
            mc.connectAttr(con.lAttr(self.local_static,lname),mdl+".i1")
            mc.connectAttr(con.lAttr(self.local_static,con.lname(lname,ac.offset)),mdl+".i2")
            
            fc_mdl = mc.createNode(ntc.tMultDoubleLinear,name=con.lname(lname,sc.sFc,i,sc.sMdl))
            mc.connectAttr(mdl+".o",fc_mdl+".i1")
            _fc = mc.createNode(ntc.tFrameCache,name=con.lname(lname,i, sc.sFc))
            mc.connectAttr(driver_key + ".o", _fc + ".s")
            mc.setAttr(_fc + ".vt", loc_count)
            if prefix ==  fc.rt:
                mc.setAttr(_fc + ".vt", 1-loc_count)

            #     mc.connectAttr(_fc + ".v",fc_mdl+".i2")
            # else:
                
            rev = mc.createNode(ntc.tReverse, name=con.lname(_fc, sc.sRee))
            mc.connectAttr(_fc + ".v", rev + ".ix")
            mc.connectAttr(rev+".ox",fc_mdl+".i2")
            mc.connectAttr(fc_mdl+".o",con.lAttr(loc,_attr))
            
            
        
        return
    
    def parentConstraint_driver(self,loc_list,driver_key,_lf_loc, _rt_loc, _cr_loc,skip = False):
        
        locNum = len(loc_list)
        loc_crNum = (locNum - 1) / 2
        # print loc_crNum
        for i, loc in enumerate(loc_list):
            par = mc.getAttr(loc + ".parameter")
            pc_trans = con.objToType(loc, name=con.lname(loc, "trans"))
            mc.parent(pc_trans, con.lname(loc, "Zero"))
            loc_pc = con.emptyGroup(loc, ["openPc"])[0]
        
            frameCache = mc.createNode(ntc.tFrameCache, name=con.lname(loc_pc, sc.sFc))
            mc.connectAttr(driver_key + ".o", frameCache + ".s")
        
            rev = mc.createNode(ntc.tReverse, name=con.lname(frameCache, sc.sRee))
            mc.connectAttr(frameCache + ".v", rev + ".ix")
        
            if i < loc_crNum:
                mc.setAttr(frameCache + ".vt", par * 2)
            
                pc = mc.parentConstraint(_lf_loc, _cr_loc, pc_trans, mo=True)[0]
                wal = mc.parentConstraint(pc, q=True, wal=True)
                mc.connectAttr(frameCache + ".v", con.lAttr(pc, wal[1]))
                mc.connectAttr(rev + ".ox", con.lAttr(pc, wal[0]))
        
            elif i == loc_crNum:
                mc.setAttr(frameCache + ".vt", par * 2)
                pc = mc.parentConstraint(_lf_loc, _rt_loc, _cr_loc, pc_trans, mo=True)[0]
                wal = mc.parentConstraint(pc, q=True, wal=True)
                mc.connectAttr(frameCache + ".v", con.lAttr(pc, wal[2]))
                # mc.connectAttr(frameCache+".v",con.lAttr(pc,wal[1]))
                mc.connectAttr(rev + ".ox", con.lAttr(pc, wal[1]))
                mc.connectAttr(rev + ".ox", con.lAttr(pc, wal[0]))
        
            elif i > loc_crNum:
                mc.setAttr(frameCache + ".vt", 2 * (1 - par))
                # print 2*(1-par)
                pc = mc.parentConstraint(_rt_loc, _cr_loc, pc_trans, mo=True)[0]
                wal = mc.parentConstraint(pc, q=True, wal=True)
                mc.connectAttr(frameCache + ".v", con.lAttr(pc, wal[1]))
                mc.connectAttr(rev + ".ox", con.lAttr(pc, wal[0]))
                
            if not skip:
                mc.connectAttr(pc_trans + ".t", loc_pc + ".t")
            
            mc.connectAttr(pc_trans + ".r", loc_pc + ".r")
        return
    
    def lip_open_frameCache(self):
        
        _attr = con.lname(fc.mouth,fc.lip,fc.op,sc.sFc)
        mc.addAttr(self.local_static,ln=_attr,at="float",k=True)
        # mc.addAttr(self.static, ln=_attr, at="float", k=True)
        dn = con.lAttr(self.local_static,_attr)
        # dr = con.lAttr(self.static,_attr)
        # mc.setDrivenKeyframe(dn,cd=dr,dv=0,v=0,itt="linear",ott="linear")
        # mc.setDrivenKeyframe(dn,cd=dr,dv=1,v=1,itt="linear",ott="linear")
        
        mc.setKeyframe(dn,t=0,v=0,itt="spline",ott="spline")
        mc.setKeyframe(dn,t=1,v=1,itt="auto",ott="auto")

        return con.lname(self.local_static,_attr)

    def lip_slider_frameCache(self):
    
        _attr = con.lname(fc.mouth, fc.lip, "slider", sc.sFc)
        mc.addAttr(self.local_static, ln=_attr, at="float", k=True)
        # mc.addAttr(self.static, ln=_attr, at="float", k=True)
        dn = con.lAttr(self.local_static, _attr)
        # dr = con.lAttr(self.static,_attr)
        # mc.setDrivenKeyframe(dn,cd=dr,dv=0,v=0,itt="linear",ott="linear")
        # mc.setDrivenKeyframe(dn,cd=dr,dv=1,v=1,itt="linear",ott="linear")
    
        mc.setKeyframe(dn, t=0, v=0,itt="spline",ott="spline")
        mc.setKeyframe(dn, t=0.5, v=1,itt="auto",ott="auto")
        mc.setKeyframe(dn, t=1, v=1,itt="linear",ott="linear")
    
        return con.lname(self.local_static, _attr)
    
    
    def lip_driver_ctrPoint(self,tag=fc.up,cpTag=sc.sCtr):
        lgrp = mc.createNode(ntc.tTransform,name=con.lname(fc.mouth,fc.lip,tag,cpTag+"Dr",sc.sGrp),parent=self.local_static)
        tmp_locs = mc.ls(con.lname(fc.mouth,"tmp",tag,fc.lip,cpTag,"*",sc.sLoc),fl=True)
        loc_list = list()
        jot_list = list()
        for i,tl in enumerate(tmp_locs):
            loc = mc.spaceLocator(name = con.lname(fc.mouth,fc.lip,tag,cpTag+"Dr",i+1,sc.sLoc))[0]
            locShape = con.findRelatedShape(loc)
            mc.setAttr(locShape+".localScale",0.01,0.01,0.01)
            mc.delete(mc.pointConstraint(tl,loc,mo=False))
            mc.parent(loc,lgrp)
            con.emptyGroup(loc,["Zero"])
            loc_list.append(loc)
            dv=mc.getAttr(con.lAttr(tl,ac.offset))*0.01
            mc.addAttr(loc,ln="parameter",at="float",dv=dv,k=True)
            mc.setAttr(loc+".parameter",l=True)
            if cpTag =="skin":
                con.hideShape(loc)
                jot = mc.createNode(ntc.tJoint,name = con.lname(fc.mouth,fc.lip,tag,cpTag,i+1,sc.sJot),
                                    parent=loc)
                jot_list.append(jot)
                mc.setAttr(jot+".radius",0.01)
        if jot_list:
            mc.sets(jot_list,include=self.local_sets)
        if cpTag != "skin":
            mc.hide(lgrp)
        return loc_list
    
    
    def lip_curve_driver(self):
        up_tmp_locs = mc.ls(con.lname(fc.mouth,"tmp",fc.up,fc.lip,sc.sCtr,"*",sc.sLoc))
        lo_tmp_locs = mc.ls(con.lname(fc.mouth,"tmp",fc.lo,fc.lip,sc.sCtr,"*",sc.sLoc))
        # _pts = list()
        # for locs,_tag in zip([up_tmp_locs,lo_tmp_locs],[fc.up,fc.lo]):
        #     _pts.append([mc.xform(l,q=True,ws=True,t=True) for l in locs])
        
        _pts = [[mc.xform(l,q=True,ws=True,t=True) for l in locs]
                    for locs in [up_tmp_locs,lo_tmp_locs]]
        
        # mid_value = lambda x,y: [(a+b)*.5 for a,b in zip(x,y)]
        # pts = [mid_value(ump,lmp) for ump,lmp in zip(_pts[0],_pts[1])]
        
        pts = map(lambda x,y: [(a+b)*.5 for a,b in zip(x,y)],_pts[0],_pts[1])
        
        up_main_crv = mc.rename(mc.curve(p=pts, d=3), con.lname(fc.mouth, fc.lip, fc.up, fc.main, sc.sCrv))
        lo_main_crv = mc.rename(mc.curve(p=pts, d=3), con.lname(fc.mouth, fc.lip, fc.lo, fc.main, sc.sCrv))
        
        # up_main_crv,lo_main_crv = [mc.rename(mc.curve(p=[mc.xform(l,q=True,ws=True,t=True) for l in locs],d=3),
        #                                      con.lname(fc.mouth,fc.lip,_tag,fc.main,sc.sCrv))
        #                                 for locs,_tag in zip([up_tmp_locs,lo_tmp_locs],[fc.up,fc.lo])]
        
        
        mc.hide(up_main_crv,lo_main_crv)
        return
    
    def control(self):
        
        jaw_tmp = con.lname("tmp", fc.jaw)
        jaw_ctr = cr.objToControl(jaw_tmp,name = con.lname(fc.jaw),colorId=13)
        
        mc.parent(jaw_ctr,self.local_toParent)
        jaw_rot_ctr = cr.objToControl(jaw_tmp,name = con.lname(fc.jaw,"rot"),colorId=18)
        cr.scaleXYZ(jaw_rot_ctr,0.8)
        mc.parent(jaw_rot_ctr,jaw_ctr)
        
        con.emptyGroup(jaw_ctr,)
        con.emptyGroup(jaw_rot_ctr,)
        
        for _a in ['t','r','s']:
            mc.connectAttr(jaw_ctr+"."+_a,con.lname(fc.jaw,"rot",sc.sLoc)+"."+_a)
            mc.connectAttr(jaw_rot_ctr + "." + _a, con.lname(fc.jaw,"point", sc.sLoc) + "." + _a)
            mc.connectAttr(jaw_rot_ctr + "_Sdk." + _a, con.lname(fc.jaw, "point",sc.sLoc,"Sdk") + "." + _a)
        
        mc.setDrivenKeyframe(jaw_rot_ctr+"_Sdk.ty",cd = jaw_ctr+".rx",dv=0,v=0,itt="linear",ott="linear")
        mc.setDrivenKeyframe(jaw_rot_ctr+"_Sdk.ty",cd = jaw_ctr+".rx",dv=25,v=-0.1,itt="linear",ott="linear")
        dn_sdk = con.lname(jaw_rot_ctr+"_Sdk", "translateY")
        mc.setAttr(dn_sdk + ".postInfinity", 4)
        mc.setAttr(dn_sdk + ".preInfinity", 4)
        
        mc.setDrivenKeyframe(jaw_rot_ctr + "_Sdk.sx", cd=jaw_ctr + ".rx", dv=0, v=1, itt="linear", ott="linear")
        mc.setDrivenKeyframe(jaw_rot_ctr + "_Sdk.sx", cd=jaw_ctr + ".rx", dv=25, v=0.9, itt="linear", ott="linear")
        con.lockHideAttr(jaw_ctr, ["sx", "sy", "sz", "v"])
        con.lockHideAttr(jaw_rot_ctr, ["sx", "sy", "sz", "v"])
        dn_sdk = con.lname(jaw_rot_ctr+"_Sdk", "scaleX")
        mc.setAttr(dn_sdk + ".postInfinity", 4)
        mc.setAttr(dn_sdk + ".preInfinity",4)
        # dn_sdk = con.lname(self.local_static, con.lname(lr, bc, _sn, _ul, _pn))
        # if _pn == fc.pos:
        #     mc.setAttr(dn_sdk + ".postInfinity", 3)
        # else:
        #     mc.setAttr(dn_sdk + ".preInfinity", 3)
        # -----
        
        lf_tmp = con.lname(fc.lf,"tmp",fc.corner)
        rt_tmp = con.lname(fc.rt,"tmp",fc.corner)
        
        lf_ul_tmp = con.lname(fc.lf, "tmp", fc.corner,fc.ul+"Max")
        lf_lr_tmp = con.lname(fc.lf, "tmp", fc.corner,fc.lr+"Max")
        
        sv = mc.getAttr(lf_ul_tmp+".ty")*0.1
        
        lf_corner = self.local_ctrl(lf_tmp,name=con.lname(fc.lf,fc.mouth,fc.corner),colorId=17)
        mc.parent(lf_corner,self.local_toParent)
        # con.changColor(lf_corner,18)
        con.emptyGroup(lf_corner)
        rt_corner = self.local_ctrl(lf_tmp,name=con.lname(fc.rt,fc.mouth,fc.corner),colorId=17)
        mc.parent(rt_corner,self.local_toParent)
        con.localMirror(rt_corner,space="world")
        # con.changColor(rt_corner,18)
        con.emptyGroup(rt_corner)
        
        for lr in [fc.lf,fc.rt]:
            _ctr = con.lname(lr,fc.mouth,fc.corner,sc.sCtr)
            mc.connectAttr(con.lname(lr,fc.mouth,fc.lip,fc.main,sc.sLoc,"Con")+".t",_ctr+"_Con.t")
            mc.connectAttr(con.lname(lr,fc.mouth,fc.lip,fc.main,sc.sLoc,"Con")+".r",_ctr+"_Con.r")

            mc.setAttr(_ctr+"_Sdk.s",sv,sv,sv)
            cr.rotate(_ctr,90)
            cr.scaleXYZ(_ctr,3)
            con.lockHideAttr(_ctr,ignore=["tx","ty"])
            
            dn = con.lAttr(self.local_static,con.lname(lr,fc.mouth,fc.lip,fc.ul))
            dr = con.lAttr(_ctr,"ty")
            mc.setDrivenKeyframe(dn,cd=dr,dv=0,v=0,itt="linear",ott="linear")
            mc.setDrivenKeyframe(dn,cd=dr,dv=10,v=1,itt="linear",ott="linear")
            mc.setDrivenKeyframe(dn,cd=dr,dv=-10,v=-1,itt="linear",ott="linear")
            dn_sdk = con.lname(self.local_static,con.lname(lr,fc.mouth,fc.lip,fc.ul))
            mc.setAttr(dn_sdk + ".postInfinity", 4)
            mc.setAttr(dn_sdk + ".preInfinity", 4)
            # mc.setAttr()
            
            dn = con.lAttr(self.local_static,con.lname(lr,fc.mouth,fc.lip,fc.slider))
            dr = con.lAttr(_ctr,"tx")
            mc.setDrivenKeyframe(dn,cd=dr,dv=0,v=0,itt="linear",ott="linear")
            mc.setDrivenKeyframe(dn,cd=dr,dv=10,v=1,itt="linear",ott="linear")
            mc.setDrivenKeyframe(dn,cd=dr,dv=-10,v=-1,itt="linear",ott="linear")
            dn_sdk = con.lname(self.local_static,con.lname(lr,fc.mouth,fc.lip,fc.slider))
            mc.setAttr(dn_sdk + ".postInfinity", 4)
            mc.setAttr(dn_sdk + ".preInfinity", 4)
            
            _attr = con.lname(fc.corner,ac.height)
            mc.addAttr(_ctr,ln=_attr,at="float",dv=5,k=True)
            dn = con.lAttr(self.local_static,con.lname(lr,fc.corner,ac.height))
            dr = con.lAttr(_ctr,_attr)
            mc.setDrivenKeyframe(dn,cd=dr,dv=10,v=1,itt="linear",ott="linear")
            mc.setDrivenKeyframe(dn,cd=dr,dv=0,v=0,itt="linear",ott="linear")
            dn_sdk = con.lname(self.local_static,con.lname(lr,fc.corner,ac.height))
            mc.setAttr(dn_sdk + ".postInfinity", 4)
            mc.setAttr(dn_sdk + ".preInfinity", 4)
            
            # _attr = con.lname(fc.corner, ac.soft)
            # mc.addAttr(_ctr, ln=_attr, at="float", dv=0, k=True)
            # dn = con.lAttr(self.local_static, con.lname(lr, fc.corner, ac.height))
            # dr = con.lAttr(_ctr, _attr)
            # mc.setDrivenKeyframe(dn, cd=dr, dv=10, v=1, itt="linear", ott="linear")
            # mc.setDrivenKeyframe(dn, cd=dr, dv=0, v=0, itt="linear", ott="linear")
            #
        
        for ul in [fc.up,fc.lo]:
            up_loc = con.lname(fc.mouth, fc.lip, ul, fc.main, sc.sLoc)
            # lo_loc = con.lname(fc.mouth, fc.lip, fc.lo, fc.main, sc.sLoc)
            
            up_main_ctrl  = self.local_ctrl(up_loc,name=con.lname(fc.mouth,fc.lip,ul,fc.main),colorId=17,
                                            shape="round_rectangle")
            cr.rotate(up_main_ctrl,90)
            cr.scale(up_main_ctrl,3,1.5,)
            # con.changColor(lf_corner,18)
            mc.connectAttr(up_main_ctrl+".t",up_loc+".t")
            mc.connectAttr(up_main_ctrl+".r",up_loc+".r")
            if ul == fc.lo:
                mc.parent(up_main_ctrl,jaw_rot_ctr)
            else:
                mc.parent(up_main_ctrl,self.local_toParent)
            con.emptyGroup(up_main_ctrl)
            mc.setAttr(up_main_ctrl+"_Sdk.s",sv,sv,sv)
            up_ctrl  = self.local_ctrl(up_loc,name=con.lname(fc.mouth,fc.lip,ul,),colorId=22,
                                       shape="round_rectangle")
            cr.rotate(up_ctrl,90)
            cr.scale(up_ctrl,2)
            mc.parent(up_ctrl,up_main_ctrl)
            con.channelAttrToDefault(up_ctrl)
            mc.connectAttr(up_ctrl + ".t", con.lname(fc.mouth, fc.lip, ul, sc.sLoc) + ".t")
            mc.connectAttr(up_ctrl + ".r", con.lname(fc.mouth, fc.lip, ul, sc.sLoc) + ".r")
            mc.connectAttr(up_ctrl + ".s", con.lname(fc.mouth, fc.lip, ul, sc.sLoc) + ".s")
            # mc.connectAttr(up_main_ctrl + ".s",up_loc + ".s")

            con.lockHideAttr(up_main_ctrl,["sx","sy","sz","v"])
            con.lockHideAttr(up_ctrl,["sx","sy","sz","v"])
            # con.lockHideAttr(up_ctrl,["v"])


        return
    
    def secondControl(self):
        
        lf_ul_tmp = con.lname(fc.lf, "tmp", fc.corner,fc.ul+"Max")
        sv = mc.getAttr(lf_ul_tmp+".ty")*0.1

        #Mouth_Lip_Up_ctrlDr_1_loc
        for ul in [fc.up,fc.lo]:
            loclist = mc.ls(con.lname(fc.mouth,fc.lip,ul,sc.sCtr+"Dr","*",sc.sLoc))
            locNum = (len(loclist)-1)/2
            for i,loc in enumerate(loclist):
                decompose = mc.createNode("decomposeMatrix",name = loc.replace(sc.sLoc,"dm"))
                locOut = con.emptyGroup(loc,["output"])[0]
                mc.connectAttr(locOut+".wm",decompose+".inputMatrix")
                
                _ctr = con.lname(fc.mouth,fc.lip,ul)
                ctr1 = cr.objToControl(loc, name="tmp")
                
                if i < locNum:
                    ctr = mc.rename(ctr1,con.lname(fc.lf,_ctr,i,sc.sCtr))
                elif i == locNum:
                    ctr = mc.rename(ctr1,con.lname(fc.cr, _ctr,sc.sCtr))
                elif i > locNum:
                    ctr = mc.rename(ctr1,con.lname(fc.rt, _ctr,len(loclist)-1-i ,sc.sCtr))
                    con.localMirror(ctr)
                grp = mc.createNode(ntc.tTransform,name = con.lname(ctr,"input"),parent=self.local_toParent)
                mc.connectAttr(decompose+".outputTranslate",grp+".t")
                mc.connectAttr(decompose+".outputRotate",grp+".r")
                # mc.setAttr(grp+".s",sv,sv,sv)
                ctrGrp = con.emptyGroup(ctr,["Zero"])[0]
                mc.parent(ctrGrp,grp)

                cr.scaleXYZ(ctr,sv)
                cr.rotate(ctr,90)
                con.changColor(ctr,18)
                
                mm = mc.createNode(ntc.tMultMatrix,name=con.lname(ctr,"outTranslate",sc.sMm) )
                mc.connectAttr(ctr+".wm",mm+".i[0]")
                mc.connectAttr(grp + ".wim", mm + ".i[1]")
                dcp_tans = mc.createNode("decomposeMatrix",name = con.lname(ctr,"outTranslate","dm"))
                mc.connectAttr(mm+".o",dcp_tans+".inputMatrix")
                mc.connectAttr(dcp_tans+".outputTranslate",loc+".t")
                
                con.lockHideAttr(ctr,ignore=["tx","ty","tz"])
        
        return
if __name__ == '__main__':
    pass